<template>
  <div class="platform-title">热浪-珊瑚-浮游生物生态影响可视化平台</div>
  <div class="progress-bar" v-if="loading"></div>
  <div class="container1">
    <!-- 顶部控制面板区域 -->
    <div class="top-control-panel">
      <!-- 左侧：数据类型和时间模式 -->
      <div class="left-controls">
        <div class="control-group">
          <span class="control-label">数据类型:</span>
          <div class="data-type-buttons-compact">
            <button v-for="type in dataTypes" :key="type.id"
                    @click="switchDataType(type)"
                    :class="{ active: currentDataType.id === type.id }">
              {{ type.name }}
            </button>
          </div>
        </div>
        <div class="control-group">
          <span class="control-label">筛选模式:</span>
          <div class="filter-mode-compact">
            <label>
              <input type="radio" v-model="filterMode" value="timeline">
              <span>时间轴</span>
            </label>
            <label>
              <input type="radio" v-model="filterMode" value="range">
              <span>时间段</span>
            </label>
          </div>
        </div>
      </div>

      <!-- 中间：时间控制 -->
      <div class="center-controls">
        <div class="time-display">{{ formattedDate }}</div>
        <div v-show="filterMode === 'timeline'" class="timeline-control-compact">
          <input type="range" v-model="selectedDay" :min="0" :max="totalDays" step="1" @input="updateMap"/>
          <div class="date-range-compact">
            <span>{{ startDate }}</span>
            <span>{{ endDate }}</span>
          </div>
        </div>
        <div v-show="filterMode === 'range'" class="date-range-picker-compact">
          <div class="range-inputs-compact">
            <input type="date" v-model="startSelectedDate" :min="startDate" :max="endSelectedDate || endDate"/>
            <span>至</span>
            <input type="date" v-model="endSelectedDate" :min="startSelectedDate || startDate" :max="endDate"/>
            <button @click="updateMap" class="confirm-btn-compact">确认</button>
          </div>
        </div>
      </div>

      <!-- 右侧：统计数据 -->
      <div class="right-controls">
        <div class="stats-grid-compact">
          <div class="stat-item-compact">
            <span class="stat-value-compact">{{ stats.heatwaveCount }}</span>
            <span class="stat-label-compact">热浪事件</span>
          </div>
          <div class="stat-item-compact">
            <span class="stat-value-compact">{{ stats.phytoMean.toFixed(2) }}</span>
            <span class="stat-label-compact">浮游生物</span>
          </div>
          <div class="stat-item-compact">
            <span class="stat-value-compact">{{ stats.coralMean.toFixed(2) }}</span>
            <span class="stat-label-compact">珊瑚白化</span>
          </div>
          <div class="stat-item-compact">
            <span class="stat-value-compact">{{ stats.coralMax.toFixed(2) }}</span>
            <span class="stat-label-compact">最大白化</span>
          </div>
        </div>
      </div>
    </div>

    <!-- 中间部分：主地图区域 -->
    <div class="middle-panel">
      <div class="main-panel-full">
        <div id="map-container" ref="mapContainer"></div>
        <div class="legend-container">
          <div class="legend">
            <h4>浮游生物(叶绿素a)均值</h4>
            <div class="color-scale" style="background:linear-gradient(to right,#e0f3db,#a8ddb5,#43a2ca,#0868ac)"></div>
            <div class="scale-labels">
              <span>{{ phytoMin.toFixed(2) }}</span>
              <span>{{ phytoMax.toFixed(2) }}</span>
            </div>
          </div>
          <div class="legend">
            <h4>热浪强度分级</h4>
            <div class="legend-item">
              <div class="wave-symbol" style="border-color:#4CAF50"></div>
              低强度
            </div>
            <div class="legend-item">
              <div class="wave-symbol" style="border-color:#FFC107"></div>
              中等强度
            </div>
            <div class="legend-item">
              <div class="wave-symbol" style="border-color:#F44336"></div>
              高强度
            </div>
          </div>
          <div class="legend">
            <h4>工具控制</h4>
            <div class="legend-item">
              <input type="checkbox" v-model="showHexagonLayer" @change="updateMap">
              <span>显示浮游生物热力图</span>
            </div>
          </div>
        </div>
        <!-- 新增标点图例 -->
        <div class="marker-legend">
          <div class="marker-legend-title">标点图例</div>
          <div class="marker-legend-row">
            <span class="marker-dot heatwave"></span> 热浪事件
          </div>
          <div class="marker-legend-row">
            <span class="marker-dot coral"></span> 珊瑚白化
          </div>
          <div class="marker-legend-row">
            <span class="marker-dot phyto"></span> 浮游生物
          </div>
          <div class="marker-legend-note">* 颜色/形状与地图一致</div>
        </div>
      </div>
    </div>

    <!-- 下半部分：三个图表水平排列 -->
    <div>
      <router-view/>
    </div>

    <div class="lower-panel" v-show="currentDataType.id==='phyto'||currentDataType.id==='coral'">
      <div class="charts-row">
        <div class="chart-panel">
          <h4>珊瑚/浮游生物事件树形图</h4>
          <div ref="treeChart" class="chart-container"></div>
        </div>
        <div class="chart-panel">
          <h4>珊瑚/浮游生物时空分布色块图</h4>
          <div ref="heatmapChart" class="chart-container"></div>
        </div>
        <div class="chart-panel">
          <h4>热浪-浮游生物-珊瑚生态影响堆叠图</h4>
          <div ref="stackedBarChart" class="chart-container"></div>
        </div>
      </div>
    </div>
    <!-- 雷达图侧边栏 -->
    <div class="radar-sidebar" :class="{ active: showRadarSidebar }">
      <div class="sidebar-header">
        <h4>事件生态因子雷达图</h4>
        <button class="close-btn" @click="showRadarSidebar=false">×</button>
      </div>
      <div class="radar-container" v-if="selectedEvent">
        <div class="event-info">
          <div><strong>事件ID:</strong> {{ selectedEvent.event_id }}</div>
          <div><strong>开始日期:</strong> {{ selectedEvent.start_date }}</div>
          <div><strong>累计强度:</strong> {{ selectedEvent.cumulative_anomaly }}</div>
          <div><strong>最大强度:</strong> {{ selectedEvent.max_anomaly }}</div>
        </div>
        <div ref="radarChart" class="radar-chart"></div>
      </div>
    </div>
    <div v-if="showTreePopup" class="tree-popup-mask" @click.self="showTreePopup=false">
      <div class="tree-popup">
        <div class="tree-popup-title">{{ treePopupTitle }}</div>
        <div class="tree-popup-content">{{ treePopupContent }}</div>
        <button class="tree-popup-close" @click="showTreePopup=false">关闭</button>
      </div>
    </div>
  </div>
</template>

<script setup>
import {ref, onMounted, nextTick, watch} from 'vue'
import L from 'leaflet'
import 'leaflet/dist/leaflet.css'
import axios from 'axios'
import * as echarts from 'echarts'
import {useRoute, useRouter} from 'vue-router';

const router = useRouter();
const dataTypes = [
  {id: 'heatwave', name: '热浪事件'},
  {id: 'heatStrength', name: '热浪强度'},
  {id: 'phyto', name: '浮游生物'},
  {id: 'coral', name: '珊瑚白化'}
]
const currentDataType = ref(dataTypes[2])
const startDate = ref('2020-03-01')
const endDate = ref('2020-04-30')
const selectedDay = ref(0)
const totalDays = ref(60)
const filterMode = ref('timeline')
const startSelectedDate = ref('2020-03-01')
const endSelectedDate = ref('2020-04-30')
const formattedDate = ref(startDate.value)
const mapContainer = ref(null)
let map = null
let heatwaveLayer = null
let phytoHexLayer = null
let coralLayer = null
const heatwaveData = ref([])
const phytoData = ref([])
const coralData = ref([])
const stats = ref({
  heatwaveCount: 0,
  phytoMean: 0,
  coralMean: 0,
  coralMax: 0
})
const selectedEvent = ref(null)
const showRadarSidebar = ref(false)
const radarChart = ref(null)
let radarInstance = null
const stackedBarChart = ref(null)
let stackedBarInstance = null
const showHexagonLayer = ref(true)
const phytoMin = ref(0)
const phytoMax = ref(1)
const treeChart = ref(null)
const treeChartInstance = ref(null)
const heatmapChart = ref(null)
const heatmapChartInstance = ref(null)
const showTreePopup = ref(false)
const treePopupTitle = ref('')
const treePopupContent = ref('')
const treeNodeInfo = {
  '热浪事件': `热浪事件是指海洋表层水温异常升高，持续时间较长的极端气候现象。\n\n【生态影响】\n热浪事件会导致珊瑚白化、浮游生物群落结构变化、鱼类分布改变等。\n\n【研究术语】\n常用指标有DHW（累积高温周数）、最大温度异常（max anomaly）等。\n\n【案例】\n2016年大堡礁热浪导致约29%的珊瑚死亡。`,
  '珊瑚': `珊瑚是热带和亚热带海洋中的重要生态工程物种，对环境变化极为敏感。\n\n【与热浪关系】\n高温热浪会导致珊瑚白化甚至死亡。\n\n【生态作用】\n珊瑚礁为25%以上的海洋生物提供栖息地。\n\n【数据案例】\n2015-2016年全球珊瑚白化事件影响了全球70%以上的珊瑚礁。`,
  '白化': `珊瑚白化是指珊瑚因高温等压力失去共生藻，变为白色。\n\n【机制】\n共生虫黄藻流失，珊瑚失去主要能量来源。\n\n【影响】\n白化严重时会导致珊瑚大面积死亡，影响整个生态系统。\n\n【术语】\nBAA（Bleaching Alert Area）为常用白化预警指标。`,
  '死亡': `珊瑚死亡会导致珊瑚礁生态系统崩溃。\n\n【连锁反应】\n珊瑚死亡后，礁体结构退化，鱼类和无脊椎动物多样性下降。\n\n【环境影响】\n影响沿海渔业、海岸防护和碳循环。`,
  '浮游生物': `浮游生物是海洋食物链的基础，包括浮游植物和浮游动物。\n\n【与热浪关系】\n热浪可导致浮游生物群落结构变化，影响初级生产力。\n\n【生态作用】\n浮游植物通过光合作用吸收CO₂，是全球碳循环的重要环节。\n\n【数据案例】\n热浪期间，某些区域叶绿素a浓度下降30%以上。`,
  '叶绿素a': `叶绿素a是浮游植物的主要色素，是衡量初级生产力和水体富营养化的重要指标。\n\n【与环境关系】\n高温和营养盐变化会影响叶绿素a浓度。\n\n【研究术语】\nChl-a（chlorophyll-a）常用于遥感监测。`,
  '生物量': `浮游生物生物量反映了海洋生态系统的基础能量供给。\n\n【与珊瑚关系】\n浮游生物减少会影响珊瑚礁鱼类的食物来源。\n\n【案例】\n2019年热浪期间，西太平洋浮游动物生物量下降显著。`,
  '其他生态因子': `如温度、盐度、溶解氧等环境因子会影响整个生态系统的稳定性。\n\n【综合影响】\n多因子协同作用可加剧热浪对生态系统的冲击。\n\n【术语】\n多因子压力（multiple stressors）是当前生态研究热点。`,
  '海水温度': `海水温度升高是热浪事件的直接表现。\n\n【影响】\n高温可导致珊瑚白化、浮游生物死亡、鱼类分布北移。\n\n【数据案例】\n2020年日本近海表层温度比常年高2°C，导致局部珊瑚白化率超60%。`,
  '盐度': `盐度变化会影响海洋生物的生理活动和分布。\n\n【与热浪关系】\n降雨、径流增加可降低盐度，影响浮游生物和珊瑚健康。\n\n【术语】\nPSU（Practical Salinity Unit）为常用盐度单位。`
}
const loading = ref(false)

function switchDataType(type) {
  if (type.id === 'heatwave') {
    router.push(`/parent/heatwave`)
  } else if (type.id === 'heatStrength') {
    router.push(`/parent/heatStrength`)
  } else {
    router.push('/parent')
  }
  currentDataType.value = type
  updateMap()
}

async function loadData() {
  loading.value = true
  const [hw, phyto, coral] = await Promise.all([
    axios.get('/data/heatwave_events.csv'),
    axios.get('/data/phyto_data.csv'),
    axios.get('/data/coral_data.csv')
  ])
  heatwaveData.value = parseCSV(hw.data)
  phytoData.value = parseCSV(phyto.data)
  coralData.value = parseCSV(coral.data)
  totalDays.value = (new Date(endDate.value) - new Date(startDate.value)) / (1000 * 3600 * 24)
  await updateMap()
  loading.value = false
}

function parseCSV(text) {
  const lines = text.trim().split('\n')
  const headers = lines[0].split(',')
  return lines.slice(1).map(line => {
    const obj = {}
    line.split(',').forEach((val, i) => {
      obj[headers[i]] = isNaN(val) ? val : +val
    })
    return obj
  })
}

function initMap() {
  map = L.map(mapContainer.value).setView([40, 135], 5)
  L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png').addTo(map)
  updateMap()
}

async function updateMap() {
  loading.value = true
  await nextTick()
  if (heatwaveLayer) heatwaveLayer.remove()
  if (phytoHexLayer) phytoHexLayer.remove()
  if (coralLayer) coralLayer.remove()
  let dateStr
  if (filterMode.value === 'timeline') {
    const d = new Date(startDate.value)
    d.setDate(d.getDate() + Number(selectedDay.value))
    dateStr = d.toISOString().slice(0, 10)
    formattedDate.value = dateStr
  } else {
    dateStr = null
    formattedDate.value = `${startSelectedDate.value} 至 ${endSelectedDate.value}`
  }
  // 热浪事件
  let hw = heatwaveData.value
  if (filterMode.value === 'timeline') {
    hw = hw.filter(d => {
      const s = new Date(d.start_date)
      const e = new Date(s)
      e.setDate(e.getDate() + d.duration - 1)
      return dateStr >= d.start_date && dateStr <= e.toISOString().slice(0, 10)
    })
  } else {
    hw = hw.filter(d => {
      const s = new Date(d.start_date)
      const e = new Date(s)
      e.setDate(e.getDate() + d.duration - 1)
      return !(e < new Date(startSelectedDate.value) || s > new Date(endSelectedDate.value))
    })
  }
  // 限制每天渲染数量为100-200个，随机
  if (filterMode.value === 'timeline' && hw.length > 0) {
    const randomCount = Math.floor(Math.random() * 101) + 100 // 100-200
    for (let i = hw.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1))
      const temp = hw[i]
      hw[i] = hw[j]
      hw[j] = temp
    }
    hw = hw.slice(0, Math.min(randomCount, hw.length))
  }
  // 分批渲染，防止卡顿
  await new Promise(resolve => setTimeout(resolve, 0))
  heatwaveLayer = L.layerGroup(hw.map(d =>
      L.circleMarker([d.lat, d.lon], {
        radius: 8,
        color: d.max_anomaly > 4.5 ? '#F44336' : d.max_anomaly > 2.5 ? '#FFC107' : '#4CAF50',
        fillColor: d.max_anomaly > 4.5 ? '#F44336' : d.max_anomaly > 2.5 ? '#FFC107' : '#4CAF50',
        fillOpacity: 0.7
      }).bindPopup(`热浪事件ID: ${d.event_id}<br>强度: ${d.max_anomaly}`)
          .on('click', () => {
            selectedEvent.value = d
            showRadarSidebar.value = true
            nextTick(() => renderRadarChart(d))
          })
  )).addTo(map)
  await new Promise(resolve => setTimeout(resolve, 0))
  // 浮游生物数据筛选
  let phyto = phytoData.value
  if (filterMode.value === 'timeline') {
    phyto = phyto.filter(d => d.date === dateStr)
  } else {
    phyto = phyto.filter(d => d.date >= startSelectedDate.value && d.date <= endSelectedDate.value)
  }
  // 珊瑚数据筛选
  let coral = coralData.value
  if (filterMode.value === 'timeline') {
    coral = coral.filter(d => d.date === dateStr)
  } else {
    coral = coral.filter(d => d.date >= startSelectedDate.value && d.date <= endSelectedDate.value)
  }
  // 浮游生物六边形热力图
  if (showHexagonLayer.value && phyto.length > 0) {
    const vals = phyto.map(d => d.chlor_a || 0).filter(v => !isNaN(v))
    if (vals.length > 0) {
      phytoMin.value = Math.min(...vals)
      phytoMax.value = Math.max(...vals)
      const hexes = {}
      const hexSize = 1.0
      phyto.forEach(d => {
        if (d.chlor_a && !isNaN(d.chlor_a)) {
          const key = `${Math.round(d.lat / hexSize)},${Math.round(d.lon / hexSize)}`
          if (!hexes[key]) hexes[key] = []
          hexes[key].push(d.chlor_a)
        }
      })
      phytoHexLayer = L.layerGroup(Object.entries(hexes).map(([key, arr]) => {
        const [ilat, ilon] = key.split(',').map(Number)
        const lat = ilat * hexSize
        const lon = ilon * hexSize
        const avg = arr.reduce((a, b) => a + b, 0) / arr.length
        const color = getPhytoColor(avg)
        return L.polygon(getHexVertices(lat, lon, hexSize), {
          fillColor: color,
          fillOpacity: 0.5,
          color: '#1976D2',
          weight: 0.5
        }).bindPopup(`叶绿素a均值: ${avg.toFixed(3)}`)
      })).addTo(map)
    }
  }
  await new Promise(resolve => setTimeout(resolve, 0))
  // 珊瑚白化点
  if (coral.length > 0) {
    coralLayer = L.layerGroup(coral.map(d =>
        L.circleMarker([d.lat, d.lon], {
          radius: 6,
          color: d.baa > 3 ? '#0D47A1' : d.baa > 2 ? '#1976D2' : '#64B5F6',
          fillColor: d.baa > 3 ? '#0D47A1' : d.baa > 2 ? '#1976D2' : '#64B5F6',
          fillOpacity: 0.5
        }).bindPopup(`日期: ${d.date}<br>白化预警: ${d.baa}`)
    )).addTo(map)
  }
  // 修正统计计算逻辑
  stats.value.heatwaveCount = hw.length

  // 计算浮游生物统计
  const validPhyto = phyto.filter(d => d.chlor_a && !isNaN(d.chlor_a))
  stats.value.phytoMean = validPhyto.length > 0 ?
      (validPhyto.reduce((sum, d) => sum + d.chlor_a, 0) / validPhyto.length) : 0

  // 计算珊瑚统计
  const validCoral = coral.filter(d => d.baa && !isNaN(d.baa))
  stats.value.coralMean = validCoral.length > 0 ?
      (validCoral.reduce((sum, d) => sum + d.baa, 0) / validCoral.length) : 0
  stats.value.coralMax = validCoral.length > 0 ?
      Math.max(...validCoral.map(d => d.baa)) : 0

  // 为堆叠图准备数据 - 按事件ID聚合
  const eventIds = hw.map(d => d.event_id)
  const phytoByEvent = eventIds.map(id => {
    // 找到对应事件的热浪数据
    const heatwaveEvent = hw.find(h => h.event_id === id)
    if (!heatwaveEvent) return 0

    // 根据事件的时间范围和地理位置筛选浮游生物数据
    const startDate = new Date(heatwaveEvent.start_date)
    const endDate = new Date(startDate)
    endDate.setDate(endDate.getDate() + heatwaveEvent.duration - 1)

    const relatedPhyto = phytoData.value.filter(p => {
      const pDate = new Date(p.date)
      const distance = Math.sqrt(
          Math.pow(p.lat - heatwaveEvent.lat, 2) +
          Math.pow(p.lon - heatwaveEvent.lon, 2)
      )
      return pDate >= startDate && pDate <= endDate && distance < 2.0 // 2度范围内
    })

    if (relatedPhyto.length === 0) return 0
    const validPhytoData = relatedPhyto.filter(p => p.chlor_a && !isNaN(p.chlor_a))
    return validPhytoData.length > 0 ?
        (validPhytoData.reduce((sum, p) => sum + p.chlor_a, 0) / validPhytoData.length) : 0
  })

  const coralByEvent = eventIds.map(id => {
    // 找到对应事件的热浪数据
    const heatwaveEvent = hw.find(h => h.event_id === id)
    if (!heatwaveEvent) return 0

    // 根据事件的时间范围和地理位置筛选珊瑚数据
    const startDate = new Date(heatwaveEvent.start_date)
    const endDate = new Date(startDate)
    endDate.setDate(endDate.getDate() + heatwaveEvent.duration - 1)

    const relatedCoral = coralData.value.filter(c => {
      const cDate = new Date(c.date)
      const distance = Math.sqrt(
          Math.pow(c.lat - heatwaveEvent.lat, 2) +
          Math.pow(c.lon - heatwaveEvent.lon, 2)
      )
      return cDate >= startDate && cDate <= endDate && distance < 2.0 // 2度范围内
    })

    if (relatedCoral.length === 0) return 0
    const validCoralData = relatedCoral.filter(c => c.baa && !isNaN(c.baa))
    return validCoralData.length > 0 ?
        (validCoralData.reduce((sum, c) => sum + c.baa, 0) / validCoralData.length) : 0
  })

  updateStackedBarChart(hw, phytoByEvent, coralByEvent, eventIds)
  renderTreeChart()
  renderHeatmapChart()
  loading.value = false
}

function getHexVertices(lat, lon, size) {
  const vertices = []
  for (let i = 0; i < 6; i++) {
    const angle = Math.PI / 3 * i
    vertices.push([
      lat + size * Math.cos(angle),
      lon + size * Math.sin(angle)
    ])
  }
  vertices.push(vertices[0])
  return vertices
}

function getPhytoColor(val) {
  const stops = ['#e0f3db', '#a8ddb5', '#43a2ca', '#0868ac']
  const min = phytoMin.value, max = phytoMax.value
  const norm = Math.max(0, Math.min(1, (val - min) / (max - min)))
  const idx = Math.floor(norm * (stops.length - 1))
  return stops[idx]
}

function updateStackedBarChart(hw, phytoByEvent, coralByEvent, eventIds) {
  if (!stackedBarInstance) stackedBarInstance = echarts.init(stackedBarChart.value)

  // 限制显示的事件数量，避免图表过于拥挤
  const maxEvents = 20
  const displayEvents = eventIds.slice(0, maxEvents)
  const displayHeatwave = hw.slice(0, maxEvents).map(d => d.max_anomaly)
  const displayPhyto = phytoByEvent.slice(0, maxEvents)
  const displayCoral = coralByEvent.slice(0, maxEvents)

  stackedBarInstance.setOption({
    tooltip: {
      trigger: 'axis',
      formatter: function (params) {
        let result = `事件ID: ${params[0].axisValue}<br/>`
        params.forEach(param => {
          result += `${param.seriesName}: ${param.value.toFixed(3)}<br/>`
        })
        return result
      }
    },
    legend: {
      data: ['热浪强度', '浮游生物', '珊瑚白化'],
      top: 10
    },
    grid: {
      left: '3%',
      right: '4%',
      bottom: '15%',
      top: '15%',
      containLabel: true
    },
    xAxis: {
      type: 'category',
      data: displayEvents,
      axisLabel: {
        rotate: 45,
        fontSize: 10
      }
    },
    yAxis: {
      type: 'value',
      name: '数值',
      nameTextStyle: {fontSize: 12}
    },
    series: [
      {
        name: '热浪强度',
        type: 'bar',
        stack: 'total',
        data: displayHeatwave,
        itemStyle: {color: '#FF6B6B'}
      },
      {
        name: '浮游生物',
        type: 'bar',
        stack: 'total',
        data: displayPhyto,
        itemStyle: {color: '#4ECDC4'}
      },
      {
        name: '珊瑚白化',
        type: 'bar',
        stack: 'total',
        data: displayCoral,
        itemStyle: {color: '#45B7D1'}
      }
    ]
  })
}

function renderRadarChart(d) {
  if (!radarInstance) radarInstance = echarts.init(radarChart.value)

  // 根据时间范围和地理位置关联数据
  const startDate = new Date(d.start_date)
  const endDate = new Date(startDate)
  endDate.setDate(endDate.getDate() + d.duration - 1)

  const phytoArr = phytoData.value.filter(p => {
    const pDate = new Date(p.date)
    const distance = Math.sqrt(
        Math.pow(p.lat - d.lat, 2) +
        Math.pow(p.lon - d.lon, 2)
    )
    return pDate >= startDate && pDate <= endDate && distance < 2.0
  })

  const coralArr = coralData.value.filter(c => {
    const cDate = new Date(c.date)
    const distance = Math.sqrt(
        Math.pow(c.lat - d.lat, 2) +
        Math.pow(c.lon - d.lon, 2)
    )
    return cDate >= startDate && cDate <= endDate && distance < 2.0
  })

  const phytoMean = phytoArr.length ?
      (phytoArr.filter(p => p.chlor_a && !isNaN(p.chlor_a))
          .reduce((sum, p) => sum + p.chlor_a, 0) / phytoArr.filter(p => p.chlor_a && !isNaN(p.chlor_a)).length) : 0

  const coralMean = coralArr.length ?
      (coralArr.filter(c => c.baa && !isNaN(c.baa))
          .reduce((sum, c) => sum + c.baa, 0) / coralArr.filter(c => c.baa && !isNaN(c.baa)).length) : 0

  radarInstance.setOption({
    title: {text: '生态因子雷达图', textStyle: {fontSize: 14}},
    radar: {
      indicator: [
        {name: '热浪强度', max: 10},
        {name: '浮游生物', max: 1},
        {name: '珊瑚白化', max: 4}
      ],
      radius: '70%'
    },
    series: [{
      type: 'radar',
      data: [{
        value: [
          d.max_anomaly || 0,
          phytoMean,
          coralMean
        ],
        name: '生态因子',
        itemStyle: {color: '#0288d1'},
        lineStyle: {color: '#0288d1'},
        areaStyle: {color: 'rgba(2, 136, 209, 0.2)'}
      }]
    }]
  })
}

function renderTreeChart() {
  if (!treeChartInstance.value) treeChartInstance.value = echarts.init(treeChart.value)
  // 更自然分布的生态影响树
  const treeData = [
    {
      name: '热浪事件',
      itemStyle: {color: '#0288d1', borderColor: '#fff', borderWidth: 3, shadowBlur: 20, shadowColor: '#b2ebf2'},
      children: [
        {
          name: '珊瑚',
          itemStyle: {color: '#4fc3f7', borderColor: '#fff', borderWidth: 2, shadowBlur: 12, shadowColor: '#b2ebf2'},
          children: [
            {
              name: '白化',
              itemStyle: {
                color: '#b2ebf2',
                borderColor: '#fff',
                borderWidth: 1.5,
                shadowBlur: 8,
                shadowColor: '#b2ebf2'
              }
            },
            {
              name: '死亡',
              itemStyle: {
                color: '#b3e5fc',
                borderColor: '#fff',
                borderWidth: 1.5,
                shadowBlur: 8,
                shadowColor: '#b3e5fc'
              }
            }
          ]
        },
        {
          name: '浮游生物',
          itemStyle: {color: '#81d4fa', borderColor: '#fff', borderWidth: 2, shadowBlur: 12, shadowColor: '#b2ebf2'},
          children: [
            {
              name: '叶绿素a',
              itemStyle: {
                color: '#4dd0e1',
                borderColor: '#fff',
                borderWidth: 1.5,
                shadowBlur: 8,
                shadowColor: '#4dd0e1'
              }
            },
            {
              name: '生物量',
              itemStyle: {
                color: '#80cbc4',
                borderColor: '#fff',
                borderWidth: 1.5,
                shadowBlur: 8,
                shadowColor: '#80cbc4'
              }
            }
          ]
        },
        {
          name: '其他生态因子',
          itemStyle: {color: '#b2dfdb', borderColor: '#fff', borderWidth: 2, shadowBlur: 12, shadowColor: '#b2ebf2'},
          children: [
            {
              name: '海水温度',
              itemStyle: {
                color: '#aed581',
                borderColor: '#fff',
                borderWidth: 1.5,
                shadowBlur: 8,
                shadowColor: '#aed581'
              }
            },
            {
              name: '盐度',
              itemStyle: {
                color: '#fff9c4',
                borderColor: '#fff',
                borderWidth: 1.5,
                shadowBlur: 8,
                shadowColor: '#fff9c4'
              }
            }
          ]
        }
      ]
    }
  ]
  treeChartInstance.value.setOption({
    backgroundColor: '#f8fbff',
    tooltip: {trigger: 'item', backgroundColor: '#fff', borderColor: '#b2ebf2', textStyle: {color: '#0288d1'}},
    series: [{
      type: 'tree',
      data: treeData,
      top: '10%', left: '5%', bottom: '10%', right: '5%',
      symbol: 'circle',
      symbolSize: 44,
      lineStyle: {
        color: '#b2ebf2',
        width: 3,
        curveness: 0.7,
        shadowColor: '#b2ebf2',
        shadowBlur: 8
      },
      label: {
        position: 'top',
        verticalAlign: 'middle',
        align: 'center',
        color: '#e57373',
        fontSize: 16,
        fontWeight: 'bold',
        textShadowColor: '#b2ebf2',
        textShadowBlur: 4
      },
      leaves: {
        label: {
          color: '#e57373',
          fontSize: 14,
          fontWeight: 'bold',
          textShadowColor: '#b2ebf2',
          textShadowBlur: 3
        }
      },
      expandAndCollapse: false,
      initialTreeDepth: 2,
      layout: 'orthogonal',
      orient: 'LR',
      animationDuration: 800,
      animationDurationUpdate: 800
    }]
  })
  treeChartInstance.value.off('click')
  treeChartInstance.value.on('click', params => {
    const name = params.data.name
    treePopupTitle.value = name
    treePopupContent.value = treeNodeInfo[name] || '暂无介绍'
    showTreePopup.value = true
  })
}

function renderHeatmapChart() {
  if (!heatmapChartInstance.value) heatmapChartInstance.value = echarts.init(heatmapChart.value)
  // 色块图：x为日期，y为经度，值为baa/chlor_a
  const data = (currentDataType.value.id === 'coral' ? coralData.value : phytoData.value)
  const xSet = Array.from(new Set(data.map(d => d.date))).sort()
  const ySet = Array.from(new Set(data.map(d => Math.round(d.lon)))).sort((a, b) => a - b)
  const valueMap = {}
  data.forEach(d => {
    const x = xSet.indexOf(d.date)
    const y = ySet.indexOf(Math.round(d.lon))
    if (x >= 0 && y >= 0) {
      const key = `${x},${y}`
      if (!valueMap[key]) valueMap[key] = []
      valueMap[key].push(currentDataType.value.id === 'coral' ? d.baa : d.chlor_a)
    }
  })
  const heatData = Object.entries(valueMap).map(([k, arr]) => {
    const [x, y] = k.split(',').map(Number)
    return [x, y, arr.reduce((a, b) => a + b, 0) / arr.length]
  })
  heatmapChartInstance.value.setOption({
    tooltip: {
      position: 'top',
      formatter: p => `日期: ${xSet[p.value[0]]}<br/>经度: ${ySet[p.value[1]]}<br/>均值: ${p.value[2].toFixed(2)}`
    },
    grid: {height: '70%', top: '10%'},
    xAxis: {type: 'category', data: xSet, splitArea: {show: true}, axisLabel: {rotate: 45}},
    yAxis: {type: 'category', data: ySet, splitArea: {show: true}},
    visualMap: {min: 0, max: 4, calculable: true, orient: 'horizontal', left: 'center', bottom: '2%'},
    series: [{
      name: '均值', type: 'heatmap', data: heatData, label: {show: false},
      emphasis: {itemStyle: {shadowBlur: 10, shadowColor: 'rgba(0,0,0,0.5)'}}
    }]
  })
}

onMounted(async () => {
  await nextTick()
  initMap()
  await loadData()
  renderTreeChart()
  renderHeatmapChart()
})

watch([startDate, endDate, selectedDay, currentDataType], updateMap)
</script>

<style scoped>
.platform-title {
  width: 100vw;
  text-align: center;
  font-size: 2.2em;
  font-weight: bold;
  color: #0288d1;
  letter-spacing: 4px;
  padding: 28px 0 12px 0;
  background: linear-gradient(90deg, #e3f2fd 0%, #b2ebf2 100%);
  box-shadow: 0 2px 12px #b2ebf233;
  border-bottom: 2px solid #b2ebf2;
  z-index: 100;
}

.container1 {
  width: 100%;
  height: calc(100vh - 70px);
  display: flex;
  flex-direction: column;
  background: #f8fbff;
  overflow: visible !important;
}

.top-control-panel {
  flex: 0 0 auto;
  width: 100%;
  background: linear-gradient(135deg, #e8f4fd 0%, #d1ebf0 50%, #b8e0e8 100%);
  padding: 10px 20px;
  box-shadow: 0 3px 12px rgba(2, 136, 209, 0.15);
  border-bottom: 2px solid rgba(2, 136, 209, 0.2);
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 20px;
  min-height: 65px;
  position: relative;
}

.top-control-panel::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent 0%, rgba(2, 136, 209, 0.3) 50%, transparent 100%);
}

.left-controls, .center-controls, .right-controls {
  display: flex;
  align-items: center;
  gap: 20px;
  background: rgba(255, 255, 255, 0.8);
  padding: 8px 16px;
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(2, 136, 209, 0.1);
  border: 1px solid rgba(2, 136, 209, 0.15);
}

.left-controls {
  flex: 0 0 auto;
}

.center-controls {
  flex: 1;
  justify-content: center;
  max-width: 450px;
  min-width: 350px;
}

.right-controls {
  flex: 0 0 auto;
}

.control-group {
  display: flex;
  align-items: center;
  gap: 10px;
}

.control-label {
  font-size: 13px;
  color: #0277bd;
  font-weight: 600;
  white-space: nowrap;
  text-shadow: 0 1px 2px rgba(255, 255, 255, 0.8);
}

.middle-panel {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  min-height: 400px;
  overflow: visible !important;
}

.main-panel-full {
  flex: 1;
  position: relative;
  width: 100%;
  height: 100%;
  overflow: visible !important;
}

#map-container {
  width: 100%;
  height: 100%;
  min-height: 400px;
  border-radius: 8px;
  box-shadow: 0 2px 8px #0001;
  background: #fff;
  overflow: hidden;
}

.legend-container {
  position: absolute;
  top: 15px;
  left: 15px;
  z-index: 1000;
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(8px);
  border-radius: 12px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
  border: 2px solid rgba(2, 136, 209, 0.3);
  padding: 12px 16px;
  font-size: 13px;
  max-height: calc(100% - 60px);
  max-width: 280px;
  overflow-y: auto;
}

.lower-panel {
  width: 100%;
  height: 35%;
  min-height: 35vh;
  flex: 0 0 30%;
  background: #f8fbff;
  border-top: 2px solid #0288D1;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  overflow: hidden;
}

.charts-row {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: row;
  gap: 12px;
  padding: 8px 12px;
  box-sizing: border-box;
  overflow: hidden;
}

.chart-panel {
  flex: 1;
  background: #fff;
  border-radius: 6px;
  box-shadow: 0 2px 6px #0001;
  padding: 8px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.chart-panel h4 {
  margin: 0 0 6px 0;
  font-size: 18px;
  color: #0288d1;
  font-weight: bold;
  text-align: center;
  flex-shrink: 0;
}

.chart-container {
  width: 100%;
  height: calc(100% - 24px);
  min-height: 160px;
  background: #f8fbff;
  border-radius: 4px;
  overflow: hidden;
  flex: 1;
}

.coral-chart, .radar-chart {
  width: 100%;
  height: 260px;
  min-height: 200px;
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 8px #0001;
}

.radar-sidebar {
  position: fixed;
  right: 0;
  top: 0;
  width: 340px;
  height: 100vh;
  background: #fff;
  box-shadow: -2px 0 12px #1976d220;
  z-index: 1000;
  transform: translateX(100%);
  transition: transform 0.3s;
  display: flex;
  flex-direction: column;
  padding: 18px 12px;
}

.radar-sidebar.active {
  transform: translateX(0);
}

.radar-container {
  margin-top: 16px;
}

.sidebar-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.close-btn {
  background: #F44336;
  color: #fff;
  border: none;
  border-radius: 50%;
  width: 32px;
  height: 32px;
  font-size: 20px;
  cursor: pointer;
}

.tree-popup-mask {
  position: fixed;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  background: rgba(180, 220, 240, 0.25);
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
}

.tree-popup {
  background: #fff;
  border-radius: 18px;
  box-shadow: 0 0 24px #b2ebf2cc, 0 0 0 2px #b2ebf2;
  padding: 48px 56px 36px 56px;
  min-width: 480px;
  max-width: 98vw;
  color: #0288d1;
  font-size: 1.32em;
  display: flex;
  flex-direction: column;
  align-items: center;
  animation: popup-fadein 0.3s;
}

.tree-popup-title {
  font-size: 1.7em;
  font-weight: bold;
  margin-bottom: 18px;
  color: #0288d1;
  text-shadow: 0 0 8px #b2ebf2;
}

.tree-popup-content {
  margin-bottom: 28px;
  color: #0288d1;
  text-align: center;
  line-height: 1.8;
  font-size: 1.18em;
}

.tree-popup-close {
  background: linear-gradient(90deg, #b2ebf2, #4fc3f7);
  color: #0288d1;
  border: none;
  border-radius: 10px;
  padding: 10px 38px;
  font-size: 1.18em;
  font-weight: bold;
  cursor: pointer;
  box-shadow: 0 2px 8px #b2ebf233;
  transition: background 0.2s;
}

.tree-popup-close:hover {
  background: linear-gradient(90deg, #4fc3f7, #b2ebf2);
}

@keyframes popup-fadein {
  from {
    opacity: 0;
    transform: scale(0.95);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

.data-type-buttons-compact {
  display: flex;
  gap: 6px;
  align-items: center;
}

.data-type-buttons-compact button {
  padding: 6px 12px;
  border: 2px solid #0288d1;
  background: linear-gradient(145deg, #ffffff 0%, #f8fbff 100%);
  color: #0288d1;
  border-radius: 8px;
  cursor: pointer;
  font-size: 12px;
  font-weight: 600;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  white-space: nowrap;
  box-shadow: 0 2px 4px rgba(2, 136, 209, 0.15);
  position: relative;
  overflow: hidden;
}

.data-type-buttons-compact button::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);
  transition: left 0.5s;
}

.data-type-buttons-compact button:hover::before {
  left: 100%;
}

.data-type-buttons-compact button.active,
.data-type-buttons-compact button:hover {
  background: linear-gradient(145deg, #0288d1 0%, #0277bd 100%);
  color: #fff;
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(2, 136, 209, 0.3);
}

.filter-mode-compact {
  display: flex;
  gap: 0px;
  align-items: center;
  background: rgba(2, 136, 209, 0.05);
  padding: 4px;
  border-radius: 10px;
  border: 1px solid rgba(2, 136, 209, 0.2);
}

.filter-mode-compact label {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  color: #0277bd;
  cursor: pointer;
  white-space: nowrap;
  padding: 4px 8px;
  border-radius: 6px;
  transition: all 0.2s;
  font-weight: 500;
}

.filter-mode-compact label:hover {
  background: rgba(2, 136, 209, 0.1);
}

.filter-mode-compact input[type="radio"]:checked + span {
  font-weight: 700;
}

.filter-mode-compact input[type="radio"] {
  accent-color: #0288d1;
}

.time-display {
  font-size: 14px;
  color: #0277bd;
  font-weight: 700;
  text-align: center;
  margin-bottom: 6px;
  padding: 4px 12px;
  background: linear-gradient(145deg, rgba(2, 136, 209, 0.1) 0%, rgba(2, 136, 209, 0.05) 100%);
  border-radius: 8px;
  border: 1px solid rgba(2, 136, 209, 0.2);
  text-shadow: 0 1px 2px rgba(255, 255, 255, 0.8);
}

.timeline-control-compact {
  width: 100%;
  max-width: 320px;
  background: rgba(255, 255, 255, 0.5);
  padding: 6px;
  border-radius: 8px;
  border: 1px solid rgba(2, 136, 209, 0.15);
}

.timeline-control-compact input[type="range"] {
  width: 100%;
  margin: 4px 0;
  height: 6px;
  border-radius: 3px;
  background: linear-gradient(90deg, #e3f2fd 0%, #b2ebf2 100%);
  outline: none;
  -webkit-appearance: none;
}

.timeline-control-compact input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: linear-gradient(145deg, #0288d1 0%, #0277bd 100%);
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(2, 136, 209, 0.3);
  border: 2px solid #ffffff;
}

.date-range-compact {
  display: flex;
  justify-content: space-between;
  font-size: 10px;
  color: #0277bd;
  font-weight: 500;
  margin-top: 2px;
}

.range-inputs-compact {
  display: flex;
  gap: 8px;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.5);
  padding: 6px;
  border-radius: 8px;
  border: 1px solid rgba(2, 136, 209, 0.15);
}

.range-inputs-compact input[type="date"] {
  padding: 4px 6px;
  border: 2px solid rgba(2, 136, 209, 0.3);
  border-radius: 6px;
  font-size: 11px;
  width: 110px;
  background: linear-gradient(145deg, #ffffff 0%, #f8fbff 100%);
  color: #0277bd;
  font-weight: 500;
  transition: all 0.2s;
}

.range-inputs-compact input[type="date"]:focus {
  border-color: #0288d1;
  box-shadow: 0 0 0 2px rgba(2, 136, 209, 0.2);
  outline: none;
}

.range-inputs-compact span {
  font-size: 12px;
  color: #0277bd;
  font-weight: 600;
}

.confirm-btn-compact {
  padding: 4px 12px;
  background: linear-gradient(145deg, #0288d1 0%, #0277bd 100%);
  color: #fff;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-size: 11px;
  font-weight: 600;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: 0 2px 4px rgba(2, 136, 209, 0.3);
}

.confirm-btn-compact:hover {
  background: linear-gradient(145deg, #0277bd 0%, #01579b 100%);
  transform: translateY(-1px);
  box-shadow: 0 4px 8px rgba(2, 136, 209, 0.4);
}

.stats-grid-compact {
  display: flex;
  gap: 8px;
  align-items: center;
}

.stat-item-compact {
  background: linear-gradient(145deg, rgba(255, 255, 255, 0.95) 0%, rgba(248, 251, 255, 0.9) 100%);
  padding: 6px 10px;
  border-radius: 10px;
  text-align: center;
  box-shadow: 0 3px 8px rgba(2, 136, 209, 0.15);
  border: 2px solid rgba(2, 136, 209, 0.2);
  min-width: 60px;
  display: flex;
  flex-direction: column;
  position: relative;
  overflow: hidden;
  transition: all 0.3s ease;
}

.stat-item-compact::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: linear-gradient(90deg, #0288d1 0%, #4fc3f7 50%, #0288d1 100%);
}

.stat-item-compact:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 16px rgba(2, 136, 209, 0.25);
}

.stat-value-compact {
  font-size: 16px;
  font-weight: 700;
  color: #0277bd;
  line-height: 1;
  text-shadow: 0 1px 2px rgba(255, 255, 255, 0.8);
}

.stat-label-compact {
  font-size: 10px;
  color: #455a64;
  line-height: 1.1;
  margin-top: 2px;
  font-weight: 500;
}


.legend {
  margin-bottom: 16px;
  padding-bottom: 10px;
  border-bottom: 2px solid rgba(2, 136, 209, 0.2);
  background: rgba(248, 251, 255, 0.7);
  padding: 8px 10px;
  border-radius: 8px;
}

.legend:last-child {
  border-bottom: none;
  margin-bottom: 0;
}

.legend h4 {
  margin: 0 0 8px 0;
  font-size: 14px;
  color: #0277bd;
  font-weight: bold;
  text-shadow: 0 1px 2px rgba(255, 255, 255, 0.8);
}

.legend-item {
  display: flex;
  align-items: center;
  margin-bottom: 6px;
  font-size: 12px;
  color: #0277bd;
  font-weight: 500;
}

.legend-item:last-child {
  margin-bottom: 0;
}

.wave-symbol {
  width: 14px;
  height: 14px;
  border: 3px solid;
  border-radius: 50%;
  margin-right: 8px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}

.color-scale {
  height: 16px;
  border-radius: 8px;
  margin-bottom: 6px;
  border: 2px solid rgba(2, 136, 209, 0.3);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.scale-labels {
  display: flex;
  justify-content: space-between;
  font-size: 11px;
  color: #0277bd;
  font-weight: 600;
  text-shadow: 0 1px 2px rgba(255, 255, 255, 0.8);
}

.legend-item input[type="checkbox"] {
  margin-right: 6px;
  accent-color: #0288d1;
  transform: scale(1.2);
}

.legend-item span {
  color: #0277bd;
  font-weight: 500;
}

.progress-bar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 5px;
  background: linear-gradient(90deg, #0288d1 0%, #4fc3f7 100%);
  z-index: 2000;
  animation: progress-bar-ani 1.2s linear infinite;
}

@keyframes progress-bar-ani {
  0% {
    left: -100%;
    width: 30%;
  }
  50% {
    left: 35%;
    width: 50%;
  }
  100% {
    left: 100%;
    width: 30%;
  }
}

.marker-legend {
  position: absolute;
  top: 18px;
  right: 18px;
  z-index: 1000 !important;
  background: rgba(255, 255, 255, 0.97);
  border-radius: 10px;
  box-shadow: 0 2px 8px #0288d133;
  border: 2px solid #b2ebf2;
  padding: 14px 18px 10px 18px;
  min-width: 120px;
  font-size: 13px;
  color: #0288d1;
  user-select: none;
}

.marker-legend-title {
  font-weight: bold;
  font-size: 15px;
  margin-bottom: 8px;
  color: #0288d1;
  text-align: center;
}

.marker-legend-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}

.marker-dot {
  display: inline-block;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  margin-right: 2px;
  border: 3px solid #fff;
  box-shadow: 0 1px 4px #0288d122;
}

.marker-dot.heatwave {
  background: linear-gradient(135deg, #F44336 60%, #FFC107 100%);
  border-color: #F44336;
}

.marker-dot.coral {
  background: linear-gradient(135deg, #1976D2 60%, #64B5F6 100%);
  border-color: #1976D2;
}

.marker-dot.phyto {
  background: linear-gradient(135deg, #43a2ca 60%, #a8ddb5 100%);
  border-color: #43a2ca;
}

.marker-legend-note {
  font-size: 11px;
  color: #90a4ae;
  margin-top: 6px;
  text-align: center;
}

.radar-float-popup {
  position: fixed;
  top: 28px;
  right: 28px;
  width: 370px;
  background: linear-gradient(135deg, #f8fbff 60%, #e3f2fd 100%);
  border-radius: 22px;
  box-shadow: 0 8px 32px #0288d144, 0 0 0 2px #b2ebf2;
  z-index: 99999 !important;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 0 0 18px 0;
  border: 1.5px solid #b2ebf2;
  overflow: visible;
  min-height: 340px;
  animation: popup-fadein 0.25s;
}
</style>